package xyz.xmh.dao.file.impl;

import org.springframework.http.HttpHeaders;
import xyz.xmh.dao.file.FileDao;
import xyz.xmh.dao.file.ReactiveFileDao;
import xyz.xmh.pojo.entity.BaseItem;
import xyz.xmh.pojo.enums.CategoryEnum;
import xyz.xmh.pojo.enums.CheckNameEnum;
import xyz.xmh.pojo.request.file.ListRequest;
import xyz.xmh.pojo.request.file.MultiDownloadUrlRequest;
import xyz.xmh.pojo.request.file.SearchRequest;
import xyz.xmh.pojo.request.file.UpdateRequest;
import xyz.xmh.pojo.response.file.*;

import java.io.IOException;
import java.net.URLConnection;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.file.OpenOption;
import java.nio.file.Path;

/**
 * 文件操作实现类
 *
 * @author xuMingHai
 */
public class FileDaoImpl implements FileDao {

    private final ReactiveFileDao reactiveFileDao;

    public FileDaoImpl(ReactiveFileDao reactiveFileDao) {
        this.reactiveFileDao = reactiveFileDao;
    }

    @Override
    public ListResponse list() {
        return list(new ListRequest());
    }

    @Override
    public ListResponse list(ListRequest listRequest) {
        return reactiveFileDao.list(listRequest)
                .bodyToMono(ListResponse.class)
                .block();
    }

    @Override
    public SearchResponse search(String fileName) {
        return reactiveFileDao.search(fileName)
                .bodyToMono(SearchResponse.class)
                .block();
    }

    @Override
    public SearchResponse search(String fileName, CategoryEnum categoryEnum) {
        return reactiveFileDao.search(fileName, categoryEnum)
                .bodyToMono(SearchResponse.class)
                .block();
    }

    @Override
    public SearchResponse search(SearchRequest searchRequest) {
        return reactiveFileDao.search(searchRequest)
                .bodyToMono(SearchResponse.class)
                .block();
    }

    @Override
    public BaseItem get(String fileId) {
        return reactiveFileDao.get(fileId)
                .bodyToMono(BaseItem.class)
                .block();
    }

    @Override
    public DownloadUrlResponse getDownloadUrl(String fileId) {
        return reactiveFileDao.getDownloadUrl(fileId)
                .bodyToMono(DownloadUrlResponse.class)
                .block();
    }

    @Override
    public long downloadFile(String fileId, Path path, OpenOption... openOptions) {
        final DownloadUrlResponse downloadUrl = getDownloadUrl(fileId);
        try {
            final URLConnection connection = downloadUrl.getUrl().openConnection();
            connection.setDoInput(true);
            connection.setRequestProperty(HttpHeaders.REFERER, "https://www.aliyundrive.com/");
            final ReadableByteChannel readableByteChannel = Channels.newChannel(connection.getInputStream());
            final String fileName = connection.getHeaderField(HttpHeaders.CONTENT_DISPOSITION).split("''")[1];
            final FileChannel fileChannel = FileChannel.open(path.resolve(fileName), openOptions);
            final long l = fileChannel.transferFrom(readableByteChannel, 0, downloadUrl.getSize());
            if (l != downloadUrl.getSize()) {
                throw new IOException("下载异常，实际下载的字节和文件本身的字节不符。期望下载字节：" + downloadUrl.getSize() + "，实际下载字节：" + l);
            }
            readableByteChannel.close();
            fileChannel.close();
            return l;

        } catch (IOException e) {
            e.printStackTrace();
        }

        return 0;
    }

    @Override
    public MultiDownloadUrlResponse getMultiDownloadUrl(MultiDownloadUrlRequest multiDownloadUrlRequest) {
        return reactiveFileDao.getMultiDownloadUrl(multiDownloadUrlRequest)
                .bodyToMono(MultiDownloadUrlResponse.class)
                .block();
    }

    @Override
    public long multiDownloadFile(MultiDownloadUrlRequest multiDownloadUrlRequest, Path path, OpenOption... openOptions) {
        // TODO：多文件下载不能使用
        return 0;
    }

    @Override
    public CreateFolderResponse createFolder(String parentFileId, String name, CheckNameEnum checkNameEnum) {
        return reactiveFileDao.createFolder(parentFileId, name, checkNameEnum)
                .bodyToMono(CreateFolderResponse.class)
                .block();
    }

    @Override
    public CreateFolderResponse createFolder(String parentFileId, String name) {
        return reactiveFileDao.createFolder(parentFileId, name)
                .bodyToMono(CreateFolderResponse.class)
                .block();
    }

    @Override
    public CreateFolderResponse createFolder(String name) {
        return reactiveFileDao.createFolder(name)
                .bodyToMono(CreateFolderResponse.class)
                .block();
    }

    @Override
    public CreateFileResponse uploadFile(String parentFileId, Path path, CheckNameEnum checkNameEnum) {
        return reactiveFileDao.uploadFile(parentFileId, path, checkNameEnum)
                .block();
    }

    @Override
    public CreateFileResponse uploadFile(String parentFileId, Path path) {
        return reactiveFileDao.uploadFile(parentFileId, path)
                .block();
    }

    @Override
    public CreateFileResponse uploadFile(Path path) {
        return reactiveFileDao.uploadFile(path)
                .block();
    }

    @Override
    public BaseItem update(UpdateRequest updateRequest) {
        return reactiveFileDao.update(updateRequest)
                .bodyToMono(BaseItem.class)
                .block();
    }

    @Override
    public BaseItem update(String fileId, String name) {
        return reactiveFileDao.update(fileId, name)
                .bodyToMono(BaseItem.class)
                .block();
    }
}
